package com.chens.modules.storage.service;

import com.chens.common.config.FileStorageProperties;
import com.chens.common.exception.FileStorageException;
import com.chens.common.exception.MyFileNotFoundException;
import com.chens.modules.storage.model.File;
import com.chens.modules.storage.repository.FileRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.util.List;

@Service
public class FileService {

    private final Path fileStorageLocation;
    private final String uploadDir;

    @Autowired
    private FileRepository fileRepository;

    @Autowired
    public FileService(FileStorageProperties fileStorageProperties) {
        this.uploadDir = fileStorageProperties.getUploadDir();
        this.fileStorageLocation = Paths.get(uploadDir)
                .toAbsolutePath().normalize();

        try {
            Files.createDirectories(this.fileStorageLocation);
        } catch (Exception ex) {
            throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
        }
    }

    public File storeFile(MultipartFile file) {
        // Normalize file name
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());
        if (fileName == null) {
            throw new FileStorageException("File name is null.");
        }

        try {
            // Check if the file's name contains invalid characters
            if(fileName.contains("..")) {
                throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
            }

            // Copy file to the target location
            Path targetLocation = this.fileStorageLocation.resolve(fileName);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            // 构建供前端访问的路径
            // 假设静态资源映射路径为 /uploads，你可根据实际情况修改
            String relativePath = "/uploads/" + fileName;

            // Save file metadata to database
            File fileEntity = new File();
            fileEntity.setFileName(fileName);
            fileEntity.setFileType(file.getContentType());
            fileEntity.setFilePath(relativePath); // 保存相对路径
            fileEntity.setFileSize(file.getSize());
            fileEntity.setUploadTime(LocalDateTime.now());
            
            return fileRepository.save(fileEntity);
        } catch (IOException ex) {
            throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
        }
    }

    public File getFile(Long id) {
        return fileRepository.findById(id)
                .orElseThrow(() -> new MyFileNotFoundException("File not found with id " + id));
    }
    
    public List<File> getAllFiles() {
        return fileRepository.findAll();
    }
    
    public void deleteFile(Long id) {
        File file = fileRepository.findById(id)
                .orElseThrow(() -> new MyFileNotFoundException("File not found with id " + id));
        
        try {
            Path filePath = this.fileStorageLocation.resolve(file.getFileName()).normalize();
            Files.deleteIfExists(filePath);
            fileRepository.delete(file);
        } catch (IOException ex) {
            throw new FileStorageException("Could not delete file " + file.getFileName() + ". Please try again!", ex);
        }
    }

    public Page<File> getFiles(int page, int size) {
        return fileRepository.findAll(PageRequest.of(page - 1, size));
    }
}